// concurrent mode: MessageChannel
/**
 * 试想一下，如果js调用栈过长的话，布局绘制被js执行任务占用，导致掉帧，用户操作被挂起，页面无法响应；
 * 如果采用concurrent模式的话，filber的执行会被拆分，每5ms执行一次，而浏览器渲染为16ms一次，最佳情况下，
 * 单次filber的执行会特别快，在5ms没有用完时会继续执行 taskQueue 中的任务，理想情况下，我们的js在14ms左右执行完毕，
 * 留给浏览器一些绘制的时间，就可以保证60hz的页面刷新速度。
 * 而另外一个重要的特性：react调度新增了blocking模式，这种模式常常表示一些离散事件，例如用户点击，用户输入等，
 * 假如你的web应用是一个大数据展示平台，采用了SVG技术，因此页面DOM数量会特别大，DOM属性也很复杂，在react16.8之前，
 * 用户如果要进行实时搜索，页面会快速渲染，页面并不只是一个节点在变化，图谱分析应用中，页面会全部更新，react会生成和更新一整棵fiber树，
 * 导致JS长时间占用了渲染线程，用户输入会很卡顿；而concurrent模式可以很大的改善这个问题，因为正常渲染优先级为normal；
 * 离散事件优先级为blocking，大于normal，优先级较高的任务会放在taskQueue中（task按优先级排序），并且优先执行，
 * 这样一来用户的输入就能够快速的相应；当然离散事件中，我们不会考虑很长的任务，这是最佳实践的积累；
 */

let runTimes = 0;
const MAX_RUN_TIMES = 1000;

const channel = new MessageChannel();

const port = channel.port2;

const longTask = () => {
  let i = 0;
  while(i < 100000000) {
    i++;
  }
};

const runTask = () => {
  // const startTime = performance.now();
  for (let i = 0; i < 1; i++) {
    longTask();
  }

  /**
   * microtask 也会阻塞渲染，也就是说渲染事件触发循序为: 宏任务中的js，再执行当前宏中加入的微任务，最后进行布局绘制任务
   */
  // for (let i = 0; i < 10; i++) {
  //   Promise.resolve().then(() => {
  //     longTask();
  //   });
  // }
  // console.log('during: ', performance.now() - startTime);
  runTimes++;
  const ele = document.createElement('div');
  ele.innerText = `hello world -- ${runTimes}`;
  document.getElementById('root').appendChild(ele);
};

channel.port1.onmessage = () => {
  runTask();
  if (runTimes < MAX_RUN_TIMES) {
    port.postMessage(null);
  }
};

const add = () => {
  const ele = document.getElementById('count');
  const text = ele.innerText;
  ele.innerText = Number(text) + 1;
};

port.postMessage(null);
